home *** CD-ROM | disk | FTP | other *** search
- /*
- * dispatch.c This file contains the function dispatch table.
- *
- * Authors: Donald J. Becker, <becker@super.org>
- * Rick Sladkey, <jrs@world.std.com>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Olaf Kirch, <okir@monad.swb.de>
- *
- * This software may be used for any purpose provided
- * the above copyright notice is retained. It is supplied
- * as is, with no warranty expressed or implied.
- */
-
- #include "nfsd.h"
- #include "nfs_prot.h"
- #include "rpcmisc.h"
-
- /*
- * These are the global variables that hold all argument and result data.
- */
- union argument_types argument;
- union result_types result;
-
- /*
- * This is a dispatch table to simplify error checking,
- * and supply return attributes for NFS functions.
- */
-
- #ifdef __STDC__
- #define CONCAT(a,b) a##b
- #define CONCAT3(a,b,c) a##b##c
- #define STRING(a) #a
- #else
- #define CONCAT(a,b) a/**/b
- #define CONCAT3(a,b,c) a/**/b/**/c
- #define STRING(a) "a"
- #endif
-
- #define table_ent(res_type, arg_type, funct) { \
- sizeof(res_type), sizeof(arg_type), \
- (xdrproc_t) CONCAT(xdr_,res_type), \
- (xdrproc_t) CONCAT(xdr_,arg_type), \
- (int (*)()) CONCAT3(nfsd_nfsproc_,funct,_2), \
- STRING(funct), CONCAT(pr_,arg_type) \
- }
-
- /* This definition makes the first table entry use xdr_char instead of
- * xdr_void. The NULL procedure call over TCP fails for this reason
- #define nil char
- */
- #define nil void
- #define xdr_nil xdr_void
- #define pr_nil pr_void
- #define pr_char pr_void
-
- struct dispatch_entry {
- int res_size, arg_size; /* sizeof the res/arg structs */
- xdrproc_t xdr_result;
- xdrproc_t xdr_argument;
- int (*funct)(); /* function handler */
- char *name; /* name of function */
- char *(*log_print)(); /* ptr to debug handler */
- };
-
- static _PRO( char *pr_void, (void) );
- static _PRO( char *pr_nfs_fh, (nfs_fh *argp) );
- static _PRO( char *pr_sattrargs, (sattrargs *argp) );
- static _PRO( char *pr_diropargs, (diropargs *argp) );
- static _PRO( char *pr_readargs, (readargs *argp) );
- static _PRO( char *pr_writeargs, (writeargs *argp) );
- static _PRO( char *pr_createargs, (createargs *argp) );
- static _PRO( char *pr_renameargs, (renameargs *argp) );
- static _PRO( char *pr_linkargs, (linkargs *argp) );
- static _PRO( char *pr_symlinkargs, (symlinkargs *argp) );
- static _PRO( char *pr_readdirargs, (readdirargs *argp) );
-
- static struct dispatch_entry dtable[] = {
- table_ent(nil,nil,null), /* NULL */
- table_ent(attrstat,nfs_fh,getattr), /* GETATTR */
- table_ent(attrstat,sattrargs,setattr), /* SETATTR */
- table_ent(nil,nil,root), /* ROOT */
- table_ent(diropres,diropargs,lookup), /* LOOKUP */
- table_ent(readlinkres,nfs_fh,readlink), /* READLINK */
- table_ent(readres,readargs,read), /* READ */
- table_ent(nil,nil,writecache), /* WRITECACHE */
- table_ent(attrstat,writeargs,write), /* WRITE */
- table_ent(diropres,createargs,create), /* CREATE */
- table_ent(nfsstat,diropargs,remove), /* REMOVE */
- table_ent(nfsstat,renameargs,rename), /* RENAME */
- table_ent(nfsstat,linkargs,link), /* LINK */
- table_ent(nfsstat,symlinkargs,symlink), /* SYMLINK */
- table_ent(diropres,createargs,mkdir), /* MKDIR */
- table_ent(nfsstat,diropargs,rmdir), /* RMDIR */
- table_ent(readdirres,readdirargs,readdir), /* READDIR */
- table_ent(statfsres,nfs_fh,statfs), /* STATFS */
- };
-
- #ifdef CALL_PROFILING
- #define PATH_PROFILE "/tmp/nfsd.profile"
-
- static struct timeval rtimes[18] = {
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}
- };
- static int calls[18] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- };
- static struct timeval t0, t1;
- #endif
-
-
- /*
- * The main dispatch routine.
- */
- void nfs_dispatch(rqstp, transp)
- struct svc_req *rqstp;
- SVCXPRT *transp;
- {
- unsigned int proc_index = rqstp->rq_proc;
- struct dispatch_entry *dent;
-
- _rpcsvcdirty = 1;
-
- if (proc_index >= (sizeof(dtable) / sizeof(dtable[0]))) {
- svcerr_noproc(transp);
- goto done;
- }
- dent = &dtable[proc_index];
-
- #ifdef CALL_PROFILING
- gettimeofday(&t0, NULL);
- #endif
-
- /* Initialize our variables for determining the attributes of
- * the file system in nfsd.c */
- nfsclient = NULL;
-
- memset(&argument, 0, dent->arg_size);
- if (!svc_getargs(transp, dent->xdr_argument, &argument)) {
- svcerr_decode(transp);
- goto done;
- }
- /* Clear the result structure. */
- memset(&result, 0, dent->res_size);
-
- /* Log the call. The if() saves us a superfluous call to the debug
- * functions, which is a big performance win.
- */
- if (logging_enabled(D_CALL))
- log_call(rqstp, dent->name, dent->log_print(&argument));
-
- /* Do the function call itself. */
- result.nfsstat = (*dent->funct) (&argument, rqstp);
- dprintf(D_CALL, "result: %d\n", result.nfsstat);
-
- if (/* result.nfsstat >= 0 && */ /* nfsstat is unsigned? */
- !svc_sendreply(transp, dent->xdr_result, (caddr_t) & result)) {
- svcerr_systemerr(transp);
- }
- if (!svc_freeargs(transp, dent->xdr_argument, &argument)) {
- dprintf(L_ERROR, "unable to free RPC arguments, exiting\n");
- exit(1);
- }
- #ifdef CALL_PROFILING
- gettimeofday(&t1, NULL);
-
- if (t1.tv_usec < t0.tv_usec) {
- rtimes[proc_index].tv_sec += t1.tv_sec - t0.tv_sec - 1;
- rtimes[proc_index].tv_usec += 1000000 + t1.tv_usec - t0.tv_usec;
- } else {
- rtimes[proc_index].tv_sec += t1.tv_sec - t0.tv_sec;
- rtimes[proc_index].tv_usec += t1.tv_usec - t0.tv_usec;
- }
- calls[proc_index]++;
- #endif
-
- done:
- _rpcsvcdirty = 0;
- if (need_reinit) {
- reinitialize(0);
- }
- if (need_flush) {
- flush_cache(0);
- }
- }
-
- #ifdef CALL_PROFILING
- void
- dump_stats(int sig)
- {
- FILE *fp;
- int i;
-
- signal (sig, dump_stats);
-
- if ((fp = fopen(PATH_PROFILE, "w")) == NULL) {
- dprintf(L_WARNING, "unable to write profile data to %s\n",
- PATH_PROFILE);
- return;
- }
-
- for (i = 0; i < 18; i++) {
- float t;
-
- t = (float) rtimes[i].tv_sec +
- (float) rtimes[i].tv_usec / 1000000.0;
- fprintf(fp, "%-20s\t%5d calls %8.4f sec avg\n",
- dtable[i].name, calls[i],
- (calls[i])? t / calls[i] : 0);
- rtimes[i].tv_sec = rtimes[i].tv_usec = 0;
- calls[i] = 0;
- }
-
- fclose (fp);
- }
- #endif
-
-
- /*
- * Functions for debugging output. This is still risky, because malformed
- * requests could overwrite our data segment.
- */
- static char printbuf[2048];
-
- static char *pr_void()
- {
- return ("");
- }
-
- static char *pr_nfs_fh(argp)
- nfs_fh *argp;
- {
- return (fh_pr(argp));
- }
-
- static char *pr_sattrargs(argp)
- sattrargs *argp;
- {
- sprintf(printbuf, "fh:%s m:%0o u/g:%d/%d size:%d atime:%#x mtime:%#x",
- fh_pr(&argp->file), argp->attributes.mode,
- argp->attributes.uid, argp->attributes.gid,
- argp->attributes.size,
- argp->attributes.atime.seconds, argp->attributes.mtime.seconds);
- return (printbuf);
- }
-
- static char *pr_diropargs(argp)
- diropargs *argp;
- {
- sprintf(printbuf, "fh:%s n:%s", fh_pr(&(argp->dir)), argp->name);
- return (printbuf);
- }
-
- static char *pr_readargs(argp)
- readargs *argp;
- {
- sprintf(printbuf, "%s: %d bytes at %d",
- fh_pr(&argp->file), argp->count, argp->offset);
- return (printbuf);
- }
-
- static char *pr_writeargs(argp)
- writeargs *argp;
- {
- sprintf(printbuf, "%s: %d bytes at %d",
- fh_pr(&argp->file), argp->data.data_len, argp->offset);
- return (printbuf);
- }
-
- static char *pr_createargs(argp)
- createargs *argp;
- {
- sprintf(printbuf, "fh:%s n:%s m:%0o u/g:%d/%d size:%d atime:%#x mtime:%#x",
- fh_pr(&argp->where.dir), argp->where.name,
- argp->attributes.mode, argp->attributes.uid,
- argp->attributes.gid, argp->attributes.size,
- argp->attributes.atime.seconds, argp->attributes.mtime.seconds);
- return (printbuf);
- }
-
- static char *pr_renameargs(argp)
- renameargs *argp;
- {
- return ("");
- }
-
- static char *pr_linkargs(argp)
- linkargs *argp;
- {
- return ("");
- }
-
- static char *pr_symlinkargs(argp)
- symlinkargs *argp;
- {
- return ("");
- }
-
- static char *pr_readdirargs(argp)
- readdirargs *argp;
- {
- return (fh_pr(&argp->dir));
- }
-
-